package com.erp.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.beans.BeanCopier;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
public class BeanUtils {
    private BeanUtils() {
    }
    /**
     * 同属性名同类型 数据拷贝
     *
     * @param source
     * @param dest

    public static Object copy(Object source,Object dest){
    BeanCopier beanCopier = BeanCopier.create(source.getClass(), dest.getClass(), false);
    beanCopier.copy(source,dest,null);
    return dest;
    }
     */

    /**
     * 单个对象属性拷贝
     *
     * @param source 源对象
     * @param clazz  目标对象Class
     * @param <T>    目标对象类型
     * @param <M>    源对象类型
     * @return 目标对象
     */
    public static <T, M> T copyProperties(M source, Class<T> clazz) {
        if (Objects.isNull(source) || Objects.isNull(clazz)) {
            throw new IllegalArgumentException();
        }
        return copyProperties(source, clazz, null);
    }

    /**
     * 保留原source对象中的属性，同属性名 数据拷贝
     *
     * @param target 提供数据对象
     * @param source 拷贝到这个对象
     */
    public static void copyProperties(Object target, Object source) {
        if (Objects.isNull(target) || Objects.isNull(source)) {
            throw new IllegalArgumentException();
        }
        System.out.println(source.getClass());
        Field[] targetFields = source.getClass().getDeclaredFields();
        Field[] sourceFields = target.getClass().getDeclaredFields();
        try {
            for (Field targetField : targetFields) {
                if (Modifier.isStatic(targetField.getModifiers())) {
                    continue;
                }
                for (Field sourceField : sourceFields) {
                    if (targetField.getName().equals(sourceField.getName())) {
                        Method get = source.getClass().getMethod("get" + sourceField.getName().substring(0, 1).toUpperCase() + sourceField.getName().substring(1));
                        Object value = get.invoke(source);
                        Method set = target.getClass().getMethod("set" + sourceField.getName().substring(0, 1).toUpperCase() + sourceField.getName().substring(1), sourceField.getType());
                        set.invoke(target, value);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            //log.error("数据拷贝出错！", e);
        }
    }

    /**
     * 列表对象拷贝
     *
     * @param sources 源列表
     * @param clazz   源列表对象Class
     * @param <T>     目标列表对象类型
     * @param <M>     源列表对象类型
     * @return 目标列表
     */
    public static <T, M> List<T> copyObjects(List<M> sources, Class<T> clazz) {
        if (Objects.isNull(sources) || Objects.isNull(clazz) || sources.isEmpty()) {
            throw new IllegalArgumentException();
        }
        BeanCopier copier = BeanCopier.create(sources.get(0).getClass(), clazz, false);
        return Optional.of(sources)
                .orElse(new ArrayList<>())
                .stream().map(m -> copyProperties(m, clazz, copier))
                .collect(Collectors.toList());
    }

    /**
     * 单个对象属性拷贝
     *
     * @param source 源对象
     * @param clazz  目标对象Class
     * @param copier copier
     * @param <T>    目标对象类型
     * @param <M>    源对象类型
     * @return 目标对象
     */
    private static <T, M> T copyProperties(M source, Class<T> clazz, BeanCopier copier) {
        if (null == copier) {
            copier = BeanCopier.create(source.getClass(), clazz, false);
        }
        T t = null;
        try {
            t = clazz.newInstance();
            copier.copy(source, t, null);
        } catch (InstantiationException | IllegalAccessException e) {
            //log.error("单个对象属性拷贝异常: {}", e);
        }
        return t;
    }
}
